package com.joyance.springmvc.util;

import java.io.IOException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;


public class EndeUtil {

    private static String DES = "DES";

    private static String MD5 = "MD5";

    private static String RSA = "RSA";

    private static String MD5WITHRSA = "MD5withRSA";

    private String rsa_public_key;

    private String rsa_private_key;


    // des加密
    public byte[] des_encrypt(String key, String data) throws Exception {
        DESKeySpec desKeySpec = new DESKeySpec(key.getBytes());
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
        SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
        Cipher cipher = Cipher.getInstance(DES);
        SecureRandom random = new SecureRandom();
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, random);
        return cipher.doFinal(data.getBytes());
    }


    // des解密
    public byte[] des_decrypt(String key, byte[] data) throws Exception {
        DESKeySpec desKeySpec = new DESKeySpec(key.getBytes());
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
        SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
        Cipher cipher = Cipher.getInstance(DES);
        SecureRandom random = new SecureRandom();
        cipher.init(Cipher.DECRYPT_MODE, secretKey, random);
        return cipher.doFinal(data);
    }


    // md5加密
    public String Md5(String val) throws Exception {
        MessageDigest md5 = MessageDigest.getInstance(MD5);
        md5.reset();
        md5.update(val.getBytes("UTF-8"));
        byte[] bytes = md5.digest();
        StringBuffer result = new StringBuffer();
        for (int i = 0; i < bytes.length; i++) {
            if (Integer.toHexString(0xFF & bytes[i]).length() == 1)
                result.append("0").append(Integer.toHexString(0xFF & bytes[i]));
            else
                result.append(Integer.toHexString(0xFF & bytes[i]));
        }
        System.out.println(result + "_____" + result.length());
        return new String(bytes);
    }


    // 生成rsa秘钥
    public void generateRSAKey() throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA);
        keyPairGenerator.initialize(512);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        rsa_public_key = encodeByBase64(keyPair.getPublic().getEncoded());
        rsa_private_key = encodeByBase64(keyPair.getPrivate().getEncoded());
    }


    // 私钥加密
    public byte[] encryptByPrivateKey(String privateKey, String data) throws Exception {
        PKCS8EncodedKeySpec pkcS8EncodedKeySpec = new PKCS8EncodedKeySpec(decodeByBase64(privateKey));
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        PrivateKey key = keyFactory.generatePrivate(pkcS8EncodedKeySpec);
        Cipher cipher = Cipher.getInstance(RSA);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return cipher.doFinal(data.getBytes());
    }


    // 公钥解密
    public byte[] decryptByPublicKey(String publicKey, byte[] data) throws Exception {
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(decodeByBase64(publicKey));
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        PublicKey key = keyFactory.generatePublic(x509EncodedKeySpec);
        Cipher cipher = Cipher.getInstance(RSA);
        cipher.init(Cipher.DECRYPT_MODE, key);
        return cipher.doFinal(data);
    }


    // 生成签名
    public String sign(String privateKey, String data) throws Exception {
        PKCS8EncodedKeySpec pkcS8EncodedKeySpec = new PKCS8EncodedKeySpec(decodeByBase64(privateKey));
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        PrivateKey key = keyFactory.generatePrivate(pkcS8EncodedKeySpec);
        Signature signature = Signature.getInstance(MD5WITHRSA);
        signature.initSign(key);
        signature.update(data.getBytes());
        return encodeByBase64(signature.sign());
    }


    // 验证签名
    public boolean verify(String publicKey, String sign, String data) throws Exception {
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(decodeByBase64(publicKey));
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        PublicKey key = keyFactory.generatePublic(x509EncodedKeySpec);
        Signature signature = Signature.getInstance(MD5WITHRSA);
        signature.initVerify(key);
        signature.update(data.getBytes());
        return signature.verify(decodeByBase64(sign));
    }


    public String encodeByBase64(byte[] bytes) {
        return new BASE64Encoder().encode(bytes);
    }


    public byte[] decodeByBase64(String data) throws IOException {
        return new BASE64Decoder().decodeBuffer(data);
    }


    public String getRsa_public_key() {
        return rsa_public_key;
    }



    public void setRsa_public_key(String rsa_public_key) {
        this.rsa_public_key = rsa_public_key;
    }



    public String getRsa_private_key() {
        return rsa_private_key;
    }



    public void setRsa_private_key(String rsa_private_key) {
        this.rsa_private_key = rsa_private_key;
    }


    public static void main(String[] args) throws Exception {
        EndeUtil endeUtil = new EndeUtil();
        String encrypt_data = "joy_12345678joy_12345678joy_12345678joy_12345678joy_12345678joy_12345678joy_12345678";
        // String md5 = endeUtil.Md5("1345345adfasdf2");
        // System.out.println(md5);
        // des加密
        // String des_key = "joyance_key";
        // byte[] des_encrypt = endeUtil.des_encrypt(des_key, encrypt_data);
        // String encode_data = endeUtil.encodeByBase64(des_encrypt);
        // System.out.println(encode_data);
        // des解密
        // byte[] des_decrypt = endeUtil.decodeByBase64(encode_data);
        // byte[] des_decrypt_data = endeUtil.des_decrypt(des_key, des_decrypt);
        // System.out.println(new String(des_decrypt_data));
        // rsa
        endeUtil.generateRSAKey();
        String rsa_private_key_base64 = endeUtil.rsa_private_key;
        String rsa_public_key_base64 = endeUtil.rsa_public_key;
        System.out.println("privatekey base64=" + rsa_private_key_base64);
        byte[] rsa_encrypt = endeUtil.encryptByPrivateKey(rsa_private_key_base64, encrypt_data);
        String rsa_encrypt_data = endeUtil.encodeByBase64(rsa_encrypt);
        System.out.println(rsa_encrypt_data);

        byte[] rsa_decrypt = endeUtil.decodeByBase64(rsa_encrypt_data);
        byte[] rsa_decrypt_data = endeUtil.decryptByPublicKey(rsa_public_key_base64, rsa_decrypt);
        System.out.println(new String(rsa_decrypt_data));

        String sign = endeUtil.sign(rsa_private_key_base64, encrypt_data);
        System.out.println("sign=" + sign);
        boolean is_verify_success = endeUtil.verify(rsa_public_key_base64, sign, encrypt_data);
        System.out.println(is_verify_success);
    }
}
